<!--
 * 文件上传
 * @author: hexiaozhen
 * @since: 2023-10-08
 * index.vue
-->
<template>
  <div class="zc-upload">
    <a-upload :custom-request="customRequest" :disabled="disabled" v-model:file-list="fileList" @success="success">
      <template #remove-icon>
        <icon-info-circle-fill />
      </template>
      <template #upload-item="{ fileItem, index }">
        <div class="fileItem" :key="index" @click="download(fileItem)">
          <div>
            <p :class="fileItem.status === 'error' ? 'error' : ''">
              {{ fileItem.name }}
              <icon-info-circle-fill v-if="fileItem.status === 'error'" />
              <span v-if="fileItem.status === 'error'" class="retry fr" @click.stop="retryFn(fileItem)">点击重试</span>
            </p>
            <a-progress v-if="fileItem.percent !== 1" :percent="fileItem.percent" />
          </div>
          <p v-if="!disabled">
            <icon-close-circle-fill class="close" @click.stop="closeItem(fileItem, index)" />
          </p>
        </div>
      </template>
    </a-upload>
  </div>
</template>

<script setup>
import { ref, toRefs, getCurrentInstance, watch } from 'vue'
import { useUserStoreHook } from '@/store/modules/user'
import auth from '@/api/modules/auth'
import { Message } from '@arco-design/web-vue'
const { proxy } = getCurrentInstance()
const userStore = useUserStoreHook()
const props = defineProps({
  files: {
    type: Array,
    default: () => {
      return []
    },
  },
  disabled: {
    type: Boolean,
    default: false,
  },
})
const { files } = toRefs(props)
const emit = defineEmits(['submit'])
const fileList = ref(files.value)
watch(
  files,
  (val) => {
    fileList.value = val
  },
  {
    //初始化立即执行
    immediate: true,
  },
)
// 删除
const closeItem = (fileItem) => {
  fileList.value.forEach((item, index) => {
    if (item.uid === fileItem.uid || item.url === fileItem.url) {
      fileList.value.splice(index, 1)
      if (item.status !== 'error') {
        emit('submit', fileItem.uid, 'delete')
      }
    }
  })
}
const success = (fileItem) => {
  const data = JSON.parse(fileItem.response)
  emit('submit', { name: fileItem.name, url: data.data.url })
}
let uploadOption = null // 上传文件对象的方法
// 自定义上传文件
const customRequest = (option) => {
  const { onProgress, onError, onSuccess, fileItem } = option
  uploadOption = option
  const xhr = new XMLHttpRequest()
  if (xhr.upload) {
    xhr.upload.onprogress = function (event) {
      let percent
      if (event.total > 0) {
        // 0 ~ 1
        percent = Math.floor(event.loaded / event.total)
      }
      onProgress(percent, event)
    }
  }
  xhr.onerror = function error(e) {
    onError(e)
  }
  xhr.onload = function onload() {
    if (xhr.status < 200 || xhr.status >= 300) {
      if (xhr.response) {
        Message.error(JSON.parse(xhr.response).msg)
      } else {
        Message.error('服务器出错啦')
      }
      return onError(xhr.responseText)
    }
    if (JSON.parse(xhr.response).ok) {
      onSuccess(xhr.response)
    } else {
      Message.error(JSON.parse(xhr.response).msg)
      onError(xhr.response)
    }
  }

  const formData = new FormData()
  formData.append('file', fileItem.file)
  xhr.open('post', '/api/file/upload', true)
  xhr.setRequestHeader('Authorization', userStore.token)
  xhr.send(formData)

  return {
    abort() {
      xhr.abort()
    },
  }
}
// 下载
const download = (fileItem) => {
  if (!fileItem.file) {
    const param = {
      path: fileItem.url,
      fileName: fileItem.name,
    }
    auth.download(param).then((res) => {
      proxy.$commontFn.exportFile(res, fileItem.name, '')
    })
  } else {
    window.open(fileItem.url)
  }
}
// 重试
const retryFn = (fileItem) => {
  const param = {
    ...uploadOption,
    fileItem: fileItem,
  }
  customRequest(param)
}
</script>

<style lang="less" scoped>
.zc-upload {
  :deep(.arco-upload-list) {
    margin-top: 22px;
  }
  .fileItem {
    width: 100%;
    padding: @size-3 @size-5;
    box-sizing: border-box;
    background: @color-border-1;
    border-radius: 2px;
    margin-top: @size-3;
    display: flex;
    line-height: @size-6;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;

    > div {
      width: calc(100% - @size-20);
    }
    :deep(.arco-progress-line) {
      height: 6px !important;
    }
  }
  .fileItem:hover {
    background-color: @color-border-3;
  }
  .error {
    color: rgb(var(--danger-6));
  }
  .retry {
    color: rgb(var(--arcoblue-6));
    cursor: pointer;
  }
  .close {
    color: @color-text-1;
    font-size: @size-5;
    cursor: pointer;
  }
}
</style>
